package com.lx.tomcat.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class NioServer extends BaseServer<SocketChannel>{

    public NioServer() throws IOException {
    }

    public static void main(String[]args) throws IOException {
        new NioServer().accept();
    }
    Selector readSelector = Selector.open();
    @Override
    public void accept() throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // channel 非阻塞
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(8080));
        System.out.println("start port: 8080");
        // 获取Selector   多路复用选择器
        Selector selector = Selector.open();
        //绑定selector,注册事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        new Thread(new Poller()).start(); //使用poller监听Read事件
        while (true){
            if(selector.select(3000)==0)
                continue;
            System.out.println("返回就绪的channel");
            // 拿到就绪的通道集合  accept  read write
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();

            while (iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                //删除
                iterator.remove();
                // 业务逻辑
                if(!selectionKey.isValid()){
                    continue;
                }
                if (selectionKey.isAcceptable()){
                    SocketChannel socketChannel = ((ServerSocketChannel) selectionKey.channel()).accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(readSelector, SelectionKey.OP_READ);
                }
            }
        }
    }
    public class Poller implements Runnable{

        public Poller() throws IOException {
        }

        @Override
        public void run() {
            while (true){
                try {
                    if (readSelector.select(1000) == 0){
                        continue;
                    }
                    Iterator<SelectionKey> iterator = readSelector.selectedKeys().iterator();
                    while (iterator.hasNext()){
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (!key.isValid()){
                            continue;
                        }
                        if (key.isReadable()){
                            System.out.println("read");
                            SocketChannel socketChannel = (SocketChannel) key.channel();
                            request(socketChannel);
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    @Override
    protected void processor(SocketChannel socketChannel) throws IOException {
        if (!socketChannel.isConnected()){
            return;
        }
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);//缓存区
        int data = socketChannel.read(byteBuffer);
        if(data>0){
            byteBuffer.flip();
            System.out.println("读取客户端发送的数据：\n"+new String(byteBuffer.array(),0,data));
            byteBuffer.clear();

            String responseHeader="HTTP/1.1 200 \r\nContent-Type: text/html; charset=utf-8\r\n\r\n调用完成!";
            ByteBuffer buffer = ByteBuffer.wrap(responseHeader.getBytes(StandardCharsets.UTF_8));
            socketChannel.write(buffer);
            socketChannel.close();
        }else if (data == -1){
            // 客户端断开连接
            socketChannel.close();
        }
    }
}
